gusucode.com > VC++ 图片浏览器的设计与实现+设计文档源码程序 > VC++ 图片浏览器的设计与实现+设计文档源码程序/code/PictView/Lib/Gif.cpp
//Download by http://www.NewXing.com // Gif.cpp: implementation of the CGif class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include <io.h> #include <fcntl.h> #include <string.h> #include <stdio.h> #include <conio.h> #include <stdlib.h> #include "Gif.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Global variables // GIF89 Gif89 = {-1,-1,-1,0}; GIFSCREEN GifScreen; static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CGif::CGif() { ZeroDataBlock = FALSE; m_strGIFError = "No Error"; // yet m_pDib = NULL; cur_accum = 0; cur_bits = 0; maxbits = BITS; maxmaxcode = (code_int)1 << BITS; free_ent = 0; clear_flg = 0; m_pDib = NULL; } CGif::CGif(CDib *pDib) { ZeroDataBlock = FALSE; m_strGIFError = "No Error"; // yet m_pDib = NULL; cur_accum = 0; cur_bits = 0; maxbits = BITS; maxmaxcode = (code_int)1 << BITS; free_ent = 0; clear_flg = 0; m_pDib = NULL; SetDib(pDib); } CGif::~CGif() { if (m_pDib != NULL) delete m_pDib; } // free allocate memory void CGif::FreeBuffer(BYTE *Buffer) { delete[] Buffer; } // get error string CString CGif::GetErrorString() { return m_strGIFError; } // load gif file BOOL CGif::Load(LPCTSTR lpstrFileName) { UINT uWidth, uHeight, uWidthDW; // read the GIF to a packed buffer of RGB bytes BYTE *lpTmpBuffer = ReadGIFFile(lpstrFileName, &uWidth, &uHeight); if (lpTmpBuffer == NULL) return FALSE; // do this before DWORD-alignment!!! // swap red and blue for display BGRFromRGB(lpTmpBuffer, uWidth, uHeight); // now DWORD-align for display BYTE *lpBuffer = MakeDwordAlign(lpTmpBuffer, uWidth, uHeight, &uWidthDW); FreeBuffer(lpTmpBuffer); // flip for display VertFlipBuf(lpBuffer, uWidthDW, uHeight); BITMAPINFOHEADER bmiHeader; bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmiHeader.biWidth = uWidth; bmiHeader.biHeight = uHeight; bmiHeader.biPlanes = 1; bmiHeader.biBitCount = 24; bmiHeader.biCompression = BI_RGB; bmiHeader.biSizeImage = 0; bmiHeader.biXPelsPerMeter = 0; bmiHeader.biYPelsPerMeter = 0; bmiHeader.biClrUsed = 0; bmiHeader.biClrImportant = 0; // Allocate enough memory for the new CF_DIB, and copy bits DWORD dwHeaderSize = sizeof(BITMAPINFOHEADER); DWORD dwBitsSize = WIDTHBYTES(uWidth*24) * uHeight; HDIB hDIB = GlobalAlloc(GHND, dwHeaderSize + dwBitsSize); if (hDIB == NULL) return FALSE; LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); memcpy(lpDIB, (LPBYTE)&bmiHeader, dwHeaderSize); memcpy(FindDIBBits((LPBYTE)lpDIB), lpBuffer, dwBitsSize); FreeBuffer(lpBuffer); if (m_pDib != NULL) delete m_pDib; m_pDib = new CDib(); m_pDib->Attach(hDIB); return TRUE; } // save gif file BOOL CGif::Save(LPCTSTR lpstrFileName, CDib* pDib) { if (pDib == NULL) pDib = m_pDib; if (pDib == NULL) return FALSE; HDIB hDib = CopyHandle(pDib->GetHandle()); if (hDib == NULL) return FALSE; CDib* pDibTmp = new CDib; pDibTmp->Attach(hDib); //if (pDibTmp->GetBitCount() != 24) // pDibTmp->ConvertFormat(24); UINT uWidth = pDibTmp->GetWidth(); UINT uHeight = pDibTmp->GetHeight(); // convert to 8-bit image if (pDibTmp->GetBitCount() != 8) pDibTmp->ColorQuantize(8); // get 256 color r, g, b PALETTEENTRY PaletteColors[256]; pDibTmp->GetPalette()->GetPaletteEntries(0, 256, PaletteColors); int red[256], blue[256], green[256]; for (int i=0;i<256;i++) { red[i] = PaletteColors[i].peRed; green[i] = PaletteColors[i].peGreen; blue[i] = PaletteColors[i].peBlue; } // convert from DIB format (DWORD aligned, vertically flipped, red and blue swapped) BYTE *tmp = ClearDwordAlign(pDibTmp->GetBitsPtr(), uWidth, uHeight, 8); if (tmp == NULL) return FALSE; // convert from DIB VertFlipBuf(tmp, uWidth, uHeight); BOOL bSuccess = WriteGIFFile(lpstrFileName, tmp, uWidth, uHeight, 0, // background color red, green, blue); delete pDibTmp; FreeBuffer(tmp); return bSuccess; } LPBYTE CGif::ReadGIFFile(LPCTSTR lpstrFileName, UINT *uWidth, UINT *uHeight) { BYTE buf[16]; BYTE c; BYTE localColorMap[3][MAXCOLORMAPSIZE]; int useGlobalColormap; int bitPixel; int imageCount =0; char version[4]; FILE *fd; int w=0; int h=0; CString strFileName = lpstrFileName; if (strFileName.IsEmpty()) { m_strGIFError="No Name Given"; return NULL; } BYTE *bigBuf; fd=fopen(lpstrFileName,"rb"); if (fd==NULL) { m_strGIFError="Cant open GIF :\n" + strFileName; return NULL; } // read GIF file header if (!ReadOK(fd,buf,6)) { m_strGIFError="Error reading GIF Magic #\n"+strFileName; fclose(fd); return NULL; } // need the string "GIF" in the header if (strncmp((char *)buf,"GIF",3)!=0) { m_strGIFError="Error, "+strFileName+" is not a valid .GIF file"; fclose(fd); return NULL; } strncpy(version,(char *)(buf+3),3); version[3]='\0'; // only handle v 87a and 89a if ((strcmp(version,"87a")!=0)&&(strcmp(version,"89a")!=0)) { m_strGIFError="Error, Bad GIF Version number"; fclose(fd); return NULL; } // screen description if (!ReadOK(fd,buf,7)) { m_strGIFError="Error, failed to GIF read screen descriptor.\nGiving up"; fclose(fd); return NULL; } GifScreen.Width = LM_to_uint((BYTE)buf[0],(BYTE)buf[1]); GifScreen.Height = LM_to_uint((BYTE)buf[2],(BYTE)buf[3]); GifScreen.BitPixel = 2 << ((BYTE)buf[4] & 0x07); GifScreen.ColorResolution = ((((BYTE)buf[4] & 0x70) >> 3) + 1); GifScreen.BackGround= (BYTE)buf[5]; // background color... GifScreen.AspectRatio= (BYTE)buf[6]; // read colormaps if (BitSet((BYTE)buf[4],LOCALCOLORMAP)) { if (!ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap)) { m_strGIFError="Error reading GIF colormap"; fclose(fd); return NULL; } } // non-square pixels, so what? if ((GifScreen.AspectRatio!=0 ) && (GifScreen.AspectRatio!=49)) { m_strGIFError="Non-square pixels in GIF image.\nIgnoring that fact..."; } // there can be multiple images in a GIF file... uh? // what the hell do we do with multiple images? // so, we'll be interested in just the first image, cause we're lazy for(;;) { // read a byte; if (!ReadOK(fd,&c,1)) { m_strGIFError="Unexpected EOF in GIF.\nGiving up"; fclose(fd); return NULL; } // image terminator if (c==';') { } if (c=='!') { if (!ReadOK(fd,&c,1)) { m_strGIFError="Error on extension read.\nGiving up"; fclose(fd); return NULL; } DoExtension(fd,c); continue; } if (c!=',') { // Ignoring c continue; } // read image header if (!ReadOK(fd,buf,9)) { m_strGIFError="Error on dimension read\nGiving up"; fclose(fd); return NULL; } useGlobalColormap=!BitSet((BYTE)buf[8],LOCALCOLORMAP); bitPixel=1<<(((BYTE)buf[8]&0x07)+1); // let's see if we have enough mem to continue? long bufsize; if ((int)buf[5]>4) { //AfxMessageBox("This GIF file claims to be > 2000 bytes wide!",MB_OK | MB_ICONINFORMATION); } if ((int)buf[7]>4) { //AfxMessageBox("This GIF file claims to be > 2000 bytes high!",MB_OK | MB_ICONINFORMATION); } w=LM_to_uint((BYTE)buf[4],(BYTE)buf[5]); h=LM_to_uint((BYTE)buf[6],(BYTE)buf[7]); if ((w<0) || (h<0)) { m_strGIFError="Negative image dimensions!\nGiving up"; fclose(fd); return NULL; } bufsize=(long)w*(long)h; bufsize*=3; bigBuf= (BYTE *) new char [bufsize]; if (bigBuf==NULL) { m_strGIFError="Out of Memory in GIFRead"; fclose(fd); return NULL; } if (!useGlobalColormap) { if (!ReadColorMap(fd,bitPixel,localColorMap)) { m_strGIFError="Error reading GIF colormap\nGiving up"; delete [] bigBuf; fclose(fd); return NULL; } //read image if (!ReadImage(fd, bigBuf, w, h, localColorMap, BitSet((BYTE)buf[8],INTERLACE))) { m_strGIFError="Error reading GIF file\nLocalColorMap\nGiving up"; delete [] bigBuf; fclose(fd); return NULL; } } else { if (!ReadImage(fd, bigBuf, w, h, GifScreen.ColorMap, BitSet((BYTE)buf[8],INTERLACE))) { m_strGIFError="Error reading GIF file\nGIFScreen Colormap\nGiving up"; delete [] bigBuf; fclose(fd); return NULL; } } break; } *uWidth=w; *uHeight=h; fclose(fd); return bigBuf; } int CGif::ReadColorMap(FILE *fd, int number, BYTE buffer[3][MAXCOLORMAPSIZE]) { int i; BYTE rgb[3]; for (i=0;i < number; ++i) { if (!ReadOK(fd,rgb,sizeof(rgb))) { return FALSE; } buffer[CM_RED][i]=rgb[0]; buffer[CM_GREEN][i]=rgb[1]; buffer[CM_BLUE][i]=rgb[2]; } return TRUE; } int CGif::DoExtension(FILE *fd, int label) { static char buf[256]; char *str; switch(label) { case 0x01 : str="Plain Text Ext"; break; case 0xff : str= "Appl ext"; break; case 0xfe : str="Comment Ext"; while (GetDataBlock(fd,(BYTE *)buf)!=0); return FALSE; case 0XF9 : str="Graphic Ctrl Ext"; (void)GetDataBlock(fd,(BYTE *)buf); Gif89.disposal =(buf[0]>>2) &0x7; Gif89.inputFlag =(buf[0]>>1) &0x1; Gif89.delayTime =LM_to_uint(buf[1],buf[2]); if ((buf[0]&0x1)!=0) Gif89.transparent=buf[3]; while (GetDataBlock(fd,(BYTE *)buf)!=0); return FALSE; default : str=buf; sprintf(buf,"UNKNOWN (0x%02x)",label); break; } while (GetDataBlock(fd,(BYTE *)buf)!=0); return FALSE; } int CGif::GetDataBlock(FILE *fd, BYTE *buf) { BYTE count; if (!ReadOK(fd,&count,1)) { //m_strGIFError="Error in GIF DataBlock Size"; return -1; } ZeroDataBlock=count==0; if ((count!=0) && (!ReadOK(fd,buf,count))) { //m_strGIFError="Error reading GIF datablock"; return -1; } return count; } int CGif::GetCode(FILE *fd, int code_size, int flag) { static BYTE buf[280]; static int curbit, lastbit, done, last_byte; int i,j,ret; BYTE count; if (flag) { curbit=0; lastbit=0; done=FALSE; return 0; } if ((curbit+code_size) >=lastbit) { if (done) { if (curbit >=lastbit) { //m_strGIFError="Ran off the end of my bits"; return 0; } return -1; } buf[0]=buf[last_byte-2]; buf[1]=buf[last_byte-1]; if ((count=GetDataBlock(fd,&buf[2]))==0) done=TRUE; last_byte=2+count; curbit=(curbit - lastbit) + 16; lastbit = (2+count)*8; } ret=0; for (i=curbit,j=0; j<code_size;++i,++j) ret|=((buf[i/8]&(1<<(i% 8)))!=0)<<j; curbit+=code_size; return ret; } int CGif::LZWReadByte(FILE *fd, int flag, int input_code_size) { static int fresh=FALSE; int code, incode; static int code_size, set_code_size; static int max_code, max_code_size; static int firstcode, oldcode; static int clear_code, end_code; static unsigned short next[1<<MAX_LZW_BITS]; static BYTE vals[1<<MAX_LZW_BITS]; static BYTE stack [1<<(MAX_LZW_BITS+1)]; static BYTE *sp; register int i; if (flag) { set_code_size=input_code_size; code_size=set_code_size+1; clear_code=1<<set_code_size; end_code = clear_code+1; max_code = clear_code+2; max_code_size=2*clear_code; GetCode(fd,0,TRUE); fresh=TRUE; for(i=0;i<clear_code;++i) { next[i]=0; vals[i]=i; } for (;i<(1<<MAX_LZW_BITS);++i) next[i]=vals[0]=0; sp=stack; return 0; } else if (fresh) { fresh=FALSE; do { firstcode=oldcode=GetCode(fd,code_size,FALSE); } while (firstcode==clear_code); return firstcode; } if (sp > stack) return *--sp; while ((code= GetCode(fd,code_size,FALSE)) >=0) { if (code==clear_code) { for (i=0;i<clear_code;++i) { next[i]=0; vals[i]=i; } for (;i<(1<<MAX_LZW_BITS);++i) next[i]=vals[i]=0; code_size=set_code_size+1; max_code_size=2*clear_code; max_code=clear_code+2; sp=stack; firstcode=oldcode=GetCode(fd,code_size,FALSE); return firstcode; } else if (code==end_code) { int count; BYTE buf[260]; if (ZeroDataBlock) { //AfxMessageBox("ZeroDataBlock!"); //return -2;//##NEO## return 11; //原来是return 2,但是在打开Photoshop 7.0从 //test_pics中8_256.pcx转存为GIF的图片时, //会出现ZeoDataBlock错误,但如果不理会仍能正常显示 } while ((count=GetDataBlock(fd,buf)) >0); if (count!=0) { AfxMessageBox("Missing EOD in GIF data stream (common occurrence)",MB_OK); return -2; } } incode = code; if (code >= max_code) { *sp++=firstcode; code=oldcode; } while (code >=clear_code) { *sp++=vals[code]; if (code==(int)next[code]) { //m_strGIFError="Circular table entry, big GIF Error!"; return -1; } code=next[code]; } *sp++ = firstcode=vals[code]; if ((code=max_code) <(1<<MAX_LZW_BITS)) { next[code]=oldcode; vals[code]=firstcode; ++max_code; if ((max_code >=max_code_size) && (max_code_size < (1<<MAX_LZW_BITS))) { max_code_size*=2; ++code_size; } } oldcode=incode; if (sp > stack) return *--sp; } return code; } BOOL CGif::ReadImage(FILE *fd, BYTE * bigMemBuf, int width, int height, BYTE cmap[3][MAXCOLORMAPSIZE], int interlace) { BYTE c; int color; int xpos=0, ypos=0, pass=0; long curidx; if (!ReadOK(fd,& c,1)) { return FALSE; } if (LZWReadByte(fd,TRUE,c)<0) { return FALSE; } while ((color=LZWReadByte(fd,FALSE,c))>=0) { curidx=(long)xpos+(long)ypos*(long)width; curidx*=3; *(bigMemBuf+curidx)=cmap[0][color]; *(bigMemBuf+curidx+1)=cmap[1][color]; *(bigMemBuf+curidx+2)=cmap[2][color]; ++xpos; if (xpos==width) { xpos=0; if (interlace) { switch (pass) { case 0: case 1: ypos+=8; break; case 2: ypos+=4; break; case 3: ypos+=2; break; } if (ypos>=height) { ++pass; switch (pass) { case 1: ypos=4;break; case 2: ypos=2;break; case 3: ypos=1;break; default : goto fini; } } } else { ++ypos; } } if (ypos >=height) break; } fini : ASSERT(LZWReadByte(fd,FALSE,c)>=0); return TRUE; } //////////// // // GIF writing section // //////////// /* * Bump the 'curx' and 'cury' to point to the next pixel */ void CGif::BumpPixel() { /* * Bump the current X position */ ++curx; if( curx == Width ) { curx = 0; ++cury; } } /******************************************************************************* * Return the next pixel from the image *******************************************************************************/ int CGif::GIFNextPixel( ) { unsigned long index; int r; if( CountDown == 0 ) return EOF; --CountDown; index= (unsigned long)curx + (unsigned long)cury * (unsigned long)Width; r = *(buffer+index); BumpPixel(); return r; } /******************************************************************************* * here's the entry point. * file ptr, screen width, height, background color, bits per pixel and * arrays of color values (0-255) *******************************************************************************/ BOOL CGif::WriteGIFFile(LPCTSTR lpstrFileName, BYTE* buf, int GWidth, int GHeight, int BackGround, int Red[], int Green[], int Blue[]) { FILE *fp; int B; int RWidth, RHeight; int LeftOfs, TopOfs; int Resolution; int ColorMapSize; int InitCodeSize; int i; int BitsPerPixel = 8; fp=fopen(lpstrFileName,"wb"); if (fp==NULL) { m_strGIFError="Can't open GIF for writing"; return FALSE; } ColorMapSize = 1 << BitsPerPixel; buffer=buf; RWidth = Width = GWidth; RHeight = Height = GHeight; LeftOfs = TopOfs = 0; cur_accum = 0; cur_bits = 0; Resolution = BitsPerPixel; CountDown = (long)Width * (long) Height; if (BitsPerPixel <=1) InitCodeSize=2; else InitCodeSize = BitsPerPixel; curx = cury =0; fwrite("GIF87a",1,6,fp); Putword(RWidth,fp); Putword(RHeight,fp); B=0x80; B |=(Resolution -1) << 5; B |=(BitsPerPixel - 1); fputc(B,fp); fputc(BackGround,fp); fputc(0,fp); for(i=0; i<ColorMapSize; ++i) { fputc(Red[i],fp); fputc(Green[i],fp); fputc(Blue[i],fp); } fputc(',',fp); Putword(LeftOfs,fp); Putword(TopOfs,fp); Putword(Width,fp); Putword(Height,fp); fputc(0x00,fp); /* * Write out the initial code size */ fputc( InitCodeSize, fp ); /* * Go and actually compress the data */ compress( InitCodeSize+1, fp); /* * Write out a Zero-length packet (to end the series) */ fputc( 0, fp ); /* * Write the GIF file terminator */ fputc( ';', fp ); /* * And close the file */ fclose( fp ); return TRUE; } /******************************************************************************* * Write out a word to the GIF file *******************************************************************************/ void CGif::Putword(int w, FILE *fp ) { fputc( w & 0xff, fp ); fputc( (w / 256) & 0xff, fp ); } /*************************************************************************** * * GIF Image compression section * * Lempel-Ziv compression based on 'compress'. GIF modifications by * David Rowley (mgardi@watdcsu.waterloo.edu) * ***************************************************************************/ void CGif::compress( int init_bits, FILE* outfile) { register long fcode; register code_int i /* = 0 */; register int c; register code_int ent; register code_int disp; register int hshift; /* * Set up the globals: g_init_bits - initial number of bits * g_outfile - pointer to output file */ g_init_bits = init_bits; g_outfile = outfile; /* * Set up the necessary values */ clear_flg = 0; maxcode = MAXCODE(n_bits = g_init_bits); ClearCode = (1 << (init_bits - 1)); EOFCode = ClearCode + 1; free_ent = ClearCode + 2; char_init(); ent = GIFNextPixel( ); hshift = 0; for ( fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L ) ++hshift; hshift = 8 - hshift; /* set hash code range bound */ cl_hash( (count_int) HSIZE); /* clear hash table */ output( (code_int)ClearCode ); while ( (c = GIFNextPixel( )) != EOF ) { /* } */ fcode = (long) (((long) c << maxbits) + ent); i = (((code_int)c << hshift) ^ ent); /* xor hashing */ if ( htab[i] == fcode ) { ent = codetab[i]; continue; } else if ( (long)htab[i] < 0 ) /* empty slot */ goto nomatch; disp = HSIZE - i; /* secondary hash (after G. Knott) */ if ( i == 0 ) disp = 1; probe: if ( (i -= disp) < 0 ) i += HSIZE; if ( htab[i] == fcode ) { ent = codetab[i]; continue; } if ( (long)htab[i] > 0 ) goto probe; nomatch: output ( (code_int) ent ); ent = c; if ( free_ent < maxmaxcode ) { /* } */ codetab[i] = free_ent++; /* code -> hashtable */ htab[i] = fcode; } else cl_block(); } /* * Put out the final code. */ output( (code_int)ent ); output( (code_int) EOFCode ); } /***************************************************************** * TAG( output ) * * Output the given code. * Inputs: * code: A n_bits-bit integer. If == -1, then EOF. This assumes * that n_bits =< (long)wordsize - 1. * Outputs: * Outputs code to the file. * Assumptions: * Chars are 8 bits long. * Algorithm: * Maintain a BITS character long buffer (so that 8 codes will * fit in it exactly). Use the VAX insv instruction to insert each * code in turn. When the buffer fills up empty it and start over. */ void CGif::output( code_int code) { cur_accum &= masks[ cur_bits ]; if( cur_bits > 0 ) cur_accum |= ((long)code << cur_bits); else cur_accum = code; cur_bits += n_bits; while( cur_bits >= 8 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if ( free_ent > maxcode || clear_flg ) { if( clear_flg ) { maxcode = MAXCODE (n_bits = g_init_bits); clear_flg = 0; } else { ++n_bits; if ( n_bits == maxbits ) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } if( code == EOFCode ) { /* * At EOF, write the rest of the buffer. */ while( cur_bits > 0 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } flush_char(); fflush( g_outfile ); if( ferror( g_outfile ) ) { AfxMessageBox("Write Error in GIF file",MB_OK); } } } void CGif::cl_block() { cl_hash((count_int)HSIZE); free_ent=ClearCode+2; clear_flg=1; output((code_int)ClearCode); } void CGif::cl_hash(register count_int hsize) { register count_int *htab_p = htab+hsize; register long i; register long m1 = -1L; i = hsize - 16; do { *(htab_p-16)=m1; *(htab_p-15)=m1; *(htab_p-14)=m1; *(htab_p-13)=m1; *(htab_p-12)=m1; *(htab_p-11)=m1; *(htab_p-10)=m1; *(htab_p-9)=m1; *(htab_p-8)=m1; *(htab_p-7)=m1; *(htab_p-6)=m1; *(htab_p-5)=m1; *(htab_p-4)=m1; *(htab_p-3)=m1; *(htab_p-2)=m1; *(htab_p-1)=m1; htab_p-=16; } while ((i-=16) >=0); for (i+=16;i>0;--i) *--htab_p=m1; } /******************************************************************************* * GIF specific *******************************************************************************/ void CGif::char_init() { a_count=0; } void CGif::char_out(int c) { accum[a_count++]=c; if (a_count >=254) flush_char(); } void CGif::flush_char() { if (a_count > 0) { fputc(a_count,g_outfile); fwrite(accum,1,a_count,g_outfile); a_count=0; } } // // copies BYTE buffer into DWORD-aligned BYTE buffer // return addr of new buffer // BYTE* CGif::MakeDwordAlign(BYTE *dataBuf, UINT widthPix, UINT height, UINT *uiOutWidthBytes) // bytes!!! { //////////////////////////////////////////////////////////// // what's going on here? this certainly means trouble if (dataBuf==NULL) return NULL; //////////////////////////////////////////////////////////// // how big is the smallest DWORD-aligned buffer that we can use? UINT uiWidthBytes; uiWidthBytes = WIDTHBYTES(widthPix * 24); DWORD dwNewsize=(DWORD)((DWORD)uiWidthBytes * (DWORD)height); BYTE *pNew; //////////////////////////////////////////////////////////// // alloc and open our new buffer pNew=(BYTE *)new BYTE[dwNewsize]; if (pNew==NULL) { return NULL; } //////////////////////////////////////////////////////////// // copy row-by-row UINT uiInWidthBytes = widthPix * 3; UINT uiCount; for (uiCount=0;uiCount < height;uiCount++) { BYTE * bpInAdd; BYTE * bpOutAdd; ULONG lInOff; ULONG lOutOff; lInOff=uiInWidthBytes * uiCount; lOutOff=uiWidthBytes * uiCount; bpInAdd= dataBuf + lInOff; bpOutAdd= pNew + lOutOff; memcpy(bpOutAdd,bpInAdd,uiInWidthBytes); } *uiOutWidthBytes=uiWidthBytes; return pNew; } // // vertically flip a buffer // note, this operates on a buffer of widthBytes bytes, not pixels!!! // BOOL CGif::VertFlipBuf(BYTE * inbuf, UINT widthBytes, UINT height) { BYTE *tb1; BYTE *tb2; if (inbuf==NULL) return FALSE; UINT bufsize; bufsize=widthBytes; tb1= (BYTE *)new BYTE[bufsize]; if (tb1==NULL) { return FALSE; } tb2= (BYTE *)new BYTE [bufsize]; if (tb1==NULL) { return FALSE; } UINT row_cnt; ULONG off1=0; ULONG off2=0; for (row_cnt=0;row_cnt<(height+1)/2;row_cnt++) { off1=row_cnt*bufsize; off2=((height-1)-row_cnt)*bufsize; memcpy(tb1,inbuf+off1,bufsize); memcpy(tb2,inbuf+off2,bufsize); memcpy(inbuf+off1,tb2,bufsize); memcpy(inbuf+off2,tb1,bufsize); } delete [] tb1; delete [] tb2; return TRUE; } // // swap Rs and Bs // // Note! this does its stuff on buffers with a whole number of pixels // per data row!! // BOOL CGif::BGRFromRGB(BYTE *buf, UINT widthPix, UINT height) { if (buf==NULL) return FALSE; UINT col, row; for (row=0;row<height;row++) { for (col=0;col<widthPix;col++) { LPBYTE pRed, pGrn, pBlu; pRed = buf + row * widthPix * 3 + col * 3; pGrn = buf + row * widthPix * 3 + col * 3 + 1; pBlu = buf + row * widthPix * 3 + col * 3 + 2; // swap red and blue BYTE tmp; tmp = *pRed; *pRed = *pBlu; *pBlu = tmp; } } return TRUE; } BYTE* CGif::ClearDwordAlign(BYTE *inBuf, UINT widthPix, UINT height, UINT nBpp) { if (inBuf==NULL) return FALSE; BYTE *tmp; tmp=(BYTE *)new BYTE[height * widthPix * nBpp/8]; if (tmp==NULL) return NULL; UINT row; for (row=0;row<height;row++) { memcpy((tmp+row * widthPix * nBpp/8), (inBuf + row * WIDTHBYTES(widthPix * nBpp)), widthPix * nBpp/8); } return tmp; }